// 1.实现一个call函数
Function.prototype.mycall=function (context) {
    if(typeof this!=='function'){
        throw new TypeError('not function')
    }
    context=context||window;
    context.fn=this;
    let arg=[...arguments].slice(1);
    let result=context.fn(...arg);
    delete context.fn;
    return result;
};
//2.实现一个apply函数
Function.prototype.myapply=function (context) {
    if(typeof this !=='function'){
        throw new TypeError('not function');
    }
    context=context||window;
    context.fn=this;
    let result;
    if(arguments[1]){
        result =context.fn(...arguments[1])
    }else{
        result=context.fn()
    }
    delete context.fn;
    return result;
};
//3.实现一个bind函数
Function.prototype.mybind=function (context) {
    if(typeof this !=='function'){
        throw new TypeError('not function');
    }
    let _this=this;
    let arg=[...arguments].slice(1);
    return function F() {
        if(this instanceof F){
            return new _this(...arg,...arguments)
        }else{
            return _this.apply(context,arg.concat(arguments))
        }
    }
}



//4.instanceof的原理
function myInstanceof(left,right){
    let leftValue=left.__proto__;
    let rightValue=right.prototype;
    while (true){
        if (leftValue===null){
            return false
        }
        if(leftValue === rightValue){
            return true
        }
        leftValue=leftValue.__proto__;
    }
}
//5.Object.create的基本原理
function create(obj) {
    function F() {}
    F.prototype=obj;
    return new F();
}
//6 new 本质
function myNew(fun) {
    return function () {
        // const obj=Object.create(fun.prototype);
        //或者
        let obj={
            __proto__:fun.prototype
        }
        fun.call(obj,...arguments);
        return obj;
    }
}
//7继承
//--------------------------（1）原型链继承 不能给父类构造函数传递函数 所有新实例共享父类的属性
function Person(name,age) {
    this.name=name;
    this.age=age;
}
function Student(school) {
    this.school=school;
}
Student.prototype=new Person();
//--------------------------（2）构造函数继承 父类的参数传递 父类的属性和方法不可以共享
function Person(name,age) {
    this.name=name;
    this.age=age;
}
function Student(name,age,school) {
    Person.call(this,name,age);
    this.school=school;
}
//----------------------------(3)组合继承 可以传参数 可以共享父类的方法和属性 调用俩次父类构造函数
function Person(name,age) {
    this.name=name;
    this.age=age;
}
function Student(name,age,school) {
    Person.call(this,name,age);
    this.school=school;
}
Student.prototype=new Person();
Student.prototype.constructor=Student;
//------------(4)原型式继承 原型所有属性被所有实例共享
function Person(name,age) {
    this.name=name;
    this.age=age;
}
let person = new Person('小白', 18);
let student=Object(person);
//-------------(5)寄生式继承
function Person(name,age) {
    this.name=name;
    this.age=age;
}
let person = new Person('小白', 18);
function createStudent(person) {
    let student=Object.create(person);
    return student;
}
let student=createStudent(person);
//------------------------(6)寄生组合式继承
function Person(name,age) {
    this.name=name;
    this.age=age;
}
function Student(name,age,school) {
    Person.call(this,name,age);
    this.school=school;
}
Student.prototype=Object.create(Person.prototype

);
Student.prototype.constructor=Student;
//7.实现一个基本的promsie
//实现一个基本的深拷贝
// JSON.parse(JSON.stringify());
function  deepClone(obj) {
    let copy= obj instanceof Array?[]:{}
    for (let i in obj){
        if(obj.hasOwnProperty(i)){
            copy[i]=typeof obj[i]==='object'?deepClone(obj[i]):obj[i]
        }
    }
    return copy
}


